; ******************************************************************************
; * demo15.asm
; * LLP STUDIO SVP Peng
; * V1.0
; * 2023-08-28
; * 外部中断INT0、INT1联合调用实例
; * 程序正常执行时，P2口的个LED闪烁，若按INT0按钮（K3），则进入中断状态，
; * P2口LED将变成单灯移动2圈后，恢复中断前状态，继续8灯闪烁；
; * 若按INT1按钮（K4），则进入中断状态，P0口数码管将变成9 - 0循环减1，2圈后恢复
; * 中断前状态
; ******************************************************************************

ORG 0
JMP Start
ORG 03H  ; INT0中断向量起始地址
JMP Int_0
ORG 13H  ; INT1中断向量起始地址
JMP Int_1

; 主控程序开始
Start:
MOV IE, #10000101B  ; 打开总开关与EX0、EX1分路开关
MOV SP, #80H
SETB IT0  ; 采用负缘触发信号（下降沿）
SETB IT1  ; 采用负缘触发信号（下降沿）
SETB IP.0  ; 设定优先级
MOV A, #10101010B  ; 将ACC初始化
MOV DPTR, #Table

Loop:
MOV P2, A
CALL Delay
CPL A  ; 将A的内容反相
JMP Loop
; 主控程序结束

; INT0中断子程序开始
Int_0:
PUSH ACC
PUSH PSW  ; 将程序状态控制字入栈
SETB RS0  ; 切换到RB1，寄存器组切换使用定义
; 循环开始
MOV R0, #2  ; 设定2次循环

IntLoop0:
MOV A, #7FH  ; 单灯左移初始值 0111 1111
MOV R1, #8  ; 设定8次左移

IntLoop1:
MOV P2, A
CALL Delay
RR A  ; 将A的内容右移，LED左移
DJNZ R1, IntLoop1
DJNZ R0, IntLoop0
POP PSW
POP ACC
RETI
; INT0中断子程序结束

; INT1中断子程序开始
Int_1:
PUSH PSW
PUSH ACC
SETB RS1  ; 切换寄存器组，保存INT1状态，使INT0打断INT1后能返回
; 循环开始
MOV R4, #2  ; 定义中断数码管内容循环两圈

Intre3:
MOV R0, #10  ; 设定10次循环
MOV R2, #9  ; 设定初始值，准备9, 8, …, 1, 0循环
MOV P2, #1CH
MOV A, #6FH  ; "9"的字形码送至A

IntLoop2:
MOV P0, A
CALL Delay
DEC R2
MOV A, R2
MOVC A, @A + DPTR
DJNZ R0, IntLoop2
DJNZ R4, Intre3
POP ACC
POP PSW
RETI
; INT1中断子程序结束

; 0.5 s延时子程序
Delay:
MOV R7, #4
D1:
MOV R6, #200
D2:
MOV R5, #250
DJNZ R5, $
DJNZ R6, D2
DJNZ R7, D1
RET

Table:
DB 3FH, 06H, 5BH, 4FH, 66H, 6DH, 7DH, 07H, 7FH, 6FH

END
